///////////////////////////////////////////////////////////////////////////////
//
// lighthouse3D - 3D Software Library
//
// File: lh3dappmain.cpp
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2013 Marcus Reinhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////
//
// You can find a copy of the GNU General Public License (gpl.txt) in the
// directory of the library.
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// This file is the starting point for a new application using lighthouse 3D
//
///////////////////////////////////////////////////////////////////////////////

#include "lh3dappmain.h"
#include "C3DLibrary.h"
#include "C3DLibInterface.h"
#include <windows.h>

// Library Refernce
C3DLibrary *pLighthouse3D;
// Interface Instance
C3DLibInterface lighthouse3DIF;

TAppLibrarySetup tALS;

TEnvInformation *tLocalEI;

// GUI Element Handles
TGUIHandle *mainHandleUI;
TGUIHandle *windowHandle; 
TGUIHandle *buttonHandle1, *buttonHandle2, *buttonHandle3;
TGUIHandle *labelHandle1, *labelHandle2, *labelHandle3, *labelHandle4;
TGUIHandle *objectButtonHandle1, *objectButtonHandle2, *objectButtonHandle3, *objectButtonHandle4, *objectButtonHandle5;
TGUIHandle *sizeButtonHandle1, *sizeButtonHandle2, *sizeButtonHandle3, *sizeButtonHandle4;
TGUIHandle *positionButtonHandle1, *positionButtonHandle2;
TGUIHandle *posWindowHandle; 
TGUIHandle *posLabelHandle1, *posLabelHandle2, *posLabelHandle3;
TGUIHandle *actionLabelHandle1, *fpsLabelHandle;

char requestScreenUpdate = 1; // Initially update screen once
int  lastMouseX = 0, lastMouseY = 0;
int  lastLeftMousePressed, lastMiddleMousePressed, lastRightMousePressed;
char currentMenuDepth = 0, currentObjectChoosen = 0, currentObjectSize = 0;
int  currentObjectX = 0, currentObjectY = 0, currentObjectZ = 0;
int  lastAddedObject = -1, actionRotation;

int  frameCount = 0, distFPSTimer = 1, sec1, sec2;
float fps = 0;
SYSTEMTIME st1, st2;

///////////////////////////////////////////////////////////////////////////////
// lh3dappmain_event_setup( ... )
///////////////////////////////////////////////////////////////////////////////
//
// Event Task:
//
// This event is happening once at very beginning of the application and allows
//
// to override the initial renderer setup. In case a NULL ptr is returned the
//
// settings will not be changed.
//
///////////////////////////////////////////////////////////////////////////////
TAppLibrarySetup *lh3dappmain_event_setup(TEnvInformation *tEI)
{
   // Prepare init structure for renderer
   tALS.renderMode      = 2; // Texture Render enabled
   tALS.shadingMode     = 3; // Gouraud Shading enabled
   tALS.lightingMode    = 1; // Lambert Lighting enabled
   tALS.fsaaliasMode    = 0; // FSAA disabled
   tALS.texFilterMode   = 0; // Texture filter disabled
   tALS.bfcullingMode   = 0; // Back face disabled (due to potential open objects)

#ifndef __MULTI_CORE_SUPPORT
   // Run library single threaded
   tALS.nrWorkerThreads = 0; 
#else
   // Create as much workers as cores if supported by the library
   if (tEI->nrCPUCores < __CPU_CORES_SUPPORTED)
     tALS.nrWorkerThreads = tEI->nrCPUCores;   
   else
     tALS.nrWorkerThreads = __CPU_CORES_SUPPORTED;   
#endif
   // Keep reference to system environment description
   tLocalEI = tEI;

   // Return pointer to init structure (a NULL ptr won't change the defaults)
   return &tALS;
}

///////////////////////////////////////////////////////////////////////////////
// lh3dappmain_event_init( ... )
///////////////////////////////////////////////////////////////////////////////
//
// Event Task:
//
// The event is fired only once after the lighthouse renderer is created and
//
// basically initiallized. The application receives the reference to the
//
// renderer which needs to be kept for later tasks.
//
// Additionally here an initial scenary can be created, the font loaded,
//
// background picture loaded and so on.
//
///////////////////////////////////////////////////////////////////////////////
unsigned char lh3dappmain_event_init(C3DLibrary *pLibReference)
{
#ifdef __MULTI_CORE_SUPPORT
    char tempStr[64];
#endif

	// Keep reference to library for later usage
	pLighthouse3D = pLibReference;

	// Bind library to interface
	lighthouse3DIF.bindLibrary(pLighthouse3D);

	// Load initial font
	lighthouse3DIF.loadFont("../resources/basicfont.bmp");

	// Add ambient light to scene
	lighthouse3DIF.setAmbientLight(0.1);

	// Add light source to scene
	lighthouse3DIF.addDotLight(500, 500, -500, 255, 255, 255, 0.8, 0.8);

	// Add camera and activate it
	lighthouse3DIF.addCamera(0, 0, 0, 0, 0, -150, 1, 1020);
	lighthouse3DIF.setActiveCamera(0);

	// Re-place camera to position somewhere in the scene
	lighthouse3DIF.moveAheadCamera(-170);

	// Set transparency for all UI elements
	lighthouse3DIF.setGUITransparency(0.8);

	// Setup collision detection
	lighthouse3DIF.setupColDetection(_standartCollisionDetection_);
	lighthouse3DIF.setColDistance(40);

	// Setup the fog parameters
	lighthouse3DIF.setupFogSynthesis(_noFogSynthesis_);

    // Save UI Main Handle
	mainHandleUI = lighthouse3DIF.getMainHandle();

	// Create UI elements
	windowHandle  = lighthouse3DIF.createWindow(mainHandleUI, 10, 10, 160, 100, 16, "World Infos");
	buttonHandle1 = lighthouse3DIF.createButton(mainHandleUI, 10, tALS.screenHeight-32, 80, 22, "Exit");
	buttonHandle2 = lighthouse3DIF.createButton(mainHandleUI, 10, tALS.screenHeight-62, 80, 22, "Snaphot");
	buttonHandle3 = lighthouse3DIF.createButton(mainHandleUI, 10, tALS.screenHeight-92, 80, 22, "Reset Cam");
	labelHandle1  = lighthouse3DIF.createLabel(windowHandle, 6, 20, 0, "Vertexes:");
	labelHandle2  = lighthouse3DIF.createLabel(windowHandle, 6, 40, 0, "Faces:");
	labelHandle3  = lighthouse3DIF.createLabel(windowHandle, 6, 60, 0, "Reendered:");
#ifdef __MULTI_CORE_SUPPORT
	sprintf(tempStr, "Multi-Core Application (%d:%d)", tALS.nrWorkerThreads, tLocalEI->nrCPUCores);
	labelHandle4  = lighthouse3DIF.createLabel(windowHandle, 6, 80, 0, tempStr);
#else
	labelHandle4  = lighthouse3DIF.createLabel(windowHandle, 6, 80, 0, "Single-Core Application");
#endif
	objectButtonHandle1 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 10, 100, 22, "Create Pyramid");
	objectButtonHandle2 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 40, 100, 22, "Create Cube");
	objectButtonHandle3 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 70, 100, 22, "Create Cylinder");
	objectButtonHandle4 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 100, 100, 22, "Create Cone");
	objectButtonHandle5 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 130, 100, 22, "Create Sphere");

	sizeButtonHandle1 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 180, 100, 22, "Small Object");
	lighthouse3DIF.setVisible(sizeButtonHandle1, false);
	sizeButtonHandle2 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 210, 100, 22, "Medium Object");
	lighthouse3DIF.setVisible(sizeButtonHandle2, false);
	sizeButtonHandle3 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 240, 100, 22, "Large Object");
	lighthouse3DIF.setVisible(sizeButtonHandle3, false);
	sizeButtonHandle4 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 270, 100, 22, "No Object");
	lighthouse3DIF.setVisible(sizeButtonHandle4, false);

	positionButtonHandle1 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 310, 100, 22, "Create Object");
	lighthouse3DIF.setVisible(positionButtonHandle1, false);
	positionButtonHandle2= lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-110, 340, 100, 22, "No Object");
	lighthouse3DIF.setVisible(positionButtonHandle2, false);
	posWindowHandle = lighthouse3DIF.createWindow(mainHandleUI, 10, 120, 160, 80, 16, "Choose Position");
	lighthouse3DIF.setVisible(posWindowHandle, false);
	posLabelHandle1 = lighthouse3DIF.createLabel(posWindowHandle, 6, 20, 0, "x-Coordinate: 0");
	lighthouse3DIF.setVisible(posLabelHandle1, false);
	posLabelHandle2 = lighthouse3DIF.createLabel(posWindowHandle, 6, 40, 0, "y-Coordinate: 0");
	lighthouse3DIF.setVisible(posLabelHandle2, false);
	posLabelHandle3 = lighthouse3DIF.createLabel(posWindowHandle, 6, 60, 0, "z-Coordinate: 0");
	lighthouse3DIF.setVisible(posLabelHandle3, false);

	actionLabelHandle1 = lighthouse3DIF.createButton(mainHandleUI, tALS.screenWidth-220, 10, 100, 22, "Start Rotation");
	lighthouse3DIF.setVisible(actionLabelHandle1, false);

	fpsLabelHandle = lighthouse3DIF.createLabel(mainHandleUI, tALS.screenWidth-110, tALS.screenHeight-32, 0xFFFFFF, "FPS: No action");

	// Setup FPS
	distFPSTimer = 3;
	frameCount = 0;
	GetSystemTime(&st2);
	sec1 = (int) st1.wSecond;
	sec2 = (int) st2.wSecond;

	// Ok
	return 1;
}


///////////////////////////////////////////////////////////////////////////////
// lh3dapp_update_timer( ... )
///////////////////////////////////////////////////////////////////////////////
void lh3dapp_update_timer(void)
{
  char fpsText[32];

  /*
   * Calculating the frames per second
   */
  GetSystemTime(&st2);
  sec1 = (int) st1.wSecond;
  sec2 = (int) st2.wSecond;

  if ( (sec2 - sec1) >= distFPSTimer )
  {
    fps = (float)(frameCount)/(float)(distFPSTimer);
    frameCount = 0;
    GetSystemTime(&st1);
  }
  if ( (sec2 - sec1) < 0) {
    fps = -1;
    frameCount = 0;
    GetSystemTime(&st1);
  }

  frameCount++;

  if ( fps != -1 )
    sprintf(fpsText,"FpS: %i",(int)fps);
  else
    sprintf(fpsText,"FpS: ?");

  lighthouse3DIF.setCaption(fpsLabelHandle, fpsText);
}

///////////////////////////////////////////////////////////////////////////////
// lh3dapp_finalize_new_object( ... )
///////////////////////////////////////////////////////////////////////////////
unsigned char lh3dapp_finalize_new_object(int objectId, T3DPosition *objectPos) {
  if ( (objectId == lastAddedObject) && (lastAddedObject != -1) ){
    if (currentObjectX != 0)
      objectPos->xt = (float) currentObjectX;
    if (currentObjectY != 0)
      objectPos->yt = (float) currentObjectY;
    if (currentObjectZ != 0)
      objectPos->zt = (float) currentObjectZ;

    lastAddedObject = -1;
  }

  return 1;
}
	///////////////////////////////////////////////////////////////////////////////
// lh3dapp_perform_actions( ... )
///////////////////////////////////////////////////////////////////////////////
unsigned char lh3dapp_perform_actions(int objectId, T3DPosition *objectPos) {
  // Check if rotation is activated
  if (actionRotation) {
    objectPos->xr += 1;
    objectPos->yr += 1;
    objectPos->zr += 1;
  }

  return 1;
}

///////////////////////////////////////////////////////////////////////////////
// lh3dapp_periodic_application( ... )
///////////////////////////////////////////////////////////////////////////////
unsigned char lh3dapp_periodic_application(void)
{
  int i;
  unsigned char updateNecessary = 0;
  T3DPosition objectPos;
  char fpsActivated = 0;

  // Check if there are any objects in the scene
  if (lighthouse3DIF.getLastObjectReference() >= 0)
    lighthouse3DIF.setVisible(actionLabelHandle1, true);

  // Check if are currently not creating objects
  if (currentObjectChoosen == 0) {
    // Iterate over all exiting objects
	for (i=0; i <= lighthouse3DIF.getLastObjectReference(); i++) {
	  // Get object map
      objectPos = lighthouse3DIF.getObjectPosition(i);      

	  // Check if a new object was created and needs to finalized
      lh3dapp_finalize_new_object(i, &objectPos);

      // Check if an action is activated and the object needs to be processed
	  lh3dapp_perform_actions(i, &objectPos);

	  // Set object map
	  lighthouse3DIF.setObjectPosition(i, objectPos);
	} 

	// Request screen updat
	updateNecessary = 1;
	
	// Activate FPS display
	fpsActivated = 1;
  }

  // Do we have to care about FPS (requires some kind of action)
  if (fpsActivated) {
    lh3dapp_update_timer();
  }

  return updateNecessary;
}

///////////////////////////////////////////////////////////////////////////////
// lh3dapplication_main_task( ... )
///////////////////////////////////////////////////////////////////////////////
//
// Event Task:
//
// This event is created periodically (around 100 times per second). So if you
//
// want to update ojects (e.g. their position or structure) you could do it
//
// here.
//
// The return value of 0 indicates that no screen update currently is necessary.
//
// A value of 1 requests an immendiate update.
//
///////////////////////////////////////////////////////////////////////////////
unsigned char lh3dappmain_event_task(void)
{
	char tmpString[32];
	char tmpScreenUpdateRequest = requestScreenUpdate;
	
	if (lh3dapp_periodic_application())
      tmpScreenUpdateRequest = 1;

	// Clear screen update request, otherwise we provoke heavy CPU load
	requestScreenUpdate = 0;

	// If we update the screen we update the UI elements, too)
	if (tmpScreenUpdateRequest) {
  	  sprintf(tmpString, "Vertexes: %i", lighthouse3DIF.getVertexCount());
	  lighthouse3DIF.setCaption(labelHandle1, tmpString);

	  sprintf(tmpString, "Faces: %i", lighthouse3DIF.getTrianglesCount());
	  lighthouse3DIF.setCaption(labelHandle2, tmpString);

	  sprintf(tmpString, "Rendered: %i", lighthouse3DIF.getRenderedTrianglesCount());
	  lighthouse3DIF.setCaption(labelHandle3, tmpString);
	}

	// 0 = Update not necessary, 1 = Update necessary
	return tmpScreenUpdateRequest;
}

///////////////////////////////////////////////////////////////////////////////
// lh3dappmain_event_resize( ... )
///////////////////////////////////////////////////////////////////////////////
//
// Event Task:
//
// This event is thrown in case the screen size was changed. Whatever is done
//
// here (like repositioning UI elements): the screen needs an update by then.
//
///////////////////////////////////////////////////////////////////////////////
unsigned char  lh3dappmain_event_resize(int width, int height)
{
	// Keep in mind we need to request a screen update
	requestScreenUpdate = 1;

	// Ok
	return 1;
}

///////////////////////////////////////////////////////////////////////////////
// lh3dappmain_event_mousechanged( ... )
///////////////////////////////////////////////////////////////////////////////
//
// Event Task:
//
// This function implements the mouse handler. In case the left mouse button,
//
// the middle mouse button or the right mouse button was pressed or released
//
// this function is called having inside the most recent mouse coordinates.
//
// The function is also called in case only position of the mouse recently
//
// changed.
//
///////////////////////////////////////////////////////////////////////////////
unsigned char  lh3dappmain_event_mousechanged(int leftMousePressed, int middleMousePressed, int rightMousePressed, int horzPos, int vertPos)
{	
	int curMouseX = horzPos;
	int curMouseY = vertPos;
	int tmpX = 0, tmpY = 0;
	char tmpString[64];

	T3DPosition objectPos;

	// Are we currently creating an object and waiting for its position
	if (currentMenuDepth == 2) {
	  // We do
	  if (leftMousePressed) {
  	    if (!lighthouse3DIF.isOverNoGUIElement(horzPos, vertPos)) {
	      currentObjectX = (-1) * (tALS.screenWidth / 2 - horzPos);
	      currentObjectY = tALS.screenHeight / 2 - vertPos;
	      
	      sprintf(tmpString, "x-Coordinate: %i", currentObjectX);
	      lighthouse3DIF.setCaption(posLabelHandle1, tmpString);
  	      sprintf(tmpString, "y-Coordinate: %i", currentObjectY);
 	      lighthouse3DIF.setCaption(posLabelHandle2, tmpString);
	      sprintf(tmpString, "z-Coordinate: %i", currentObjectZ);
	      lighthouse3DIF.setCaption(posLabelHandle3, tmpString);
	    }
	  }
    }

	// First test for UI elements
	if ( (leftMousePressed == 1) && (lastLeftMousePressed == 0) ) {
		// Check if we clicked to the exit button
		if (lighthouse3DIF.isOverGUIElement(buttonHandle1, horzPos, vertPos)) {
		  // leave application
		  exit(0);
		}

		// Check if we clicked to the snapshot button
		if (lighthouse3DIF.isOverGUIElement(buttonHandle2, horzPos, vertPos)) {
	      lighthouse3DIF.saveSnapshot("snapshot.tga");

          // Save old mouse states
	      lastLeftMousePressed = leftMousePressed;
	      lastMiddleMousePressed = middleMousePressed;
	      lastRightMousePressed = rightMousePressed;

		  // Immediatly leave with Ok!
		  return 1;
		}

		// Check if we clicked to the reset cam button
		if (lighthouse3DIF.isOverGUIElement(buttonHandle3, horzPos, vertPos)) {
          lighthouse3DIF.resetActiveCamera();
          lighthouse3DIF.moveAheadCamera(-170);

          // Save old mouse states
	      lastLeftMousePressed = leftMousePressed;
	      lastMiddleMousePressed = middleMousePressed;
	      lastRightMousePressed = rightMousePressed;

		  // Immediatly leave with Ok!
		  return 1;
		}

		// Check if we clicked to the "action rotation button"
		if (lighthouse3DIF.isOverGUIElement(actionLabelHandle1, horzPos, vertPos)) {
		  if (actionRotation == 1) {
            lighthouse3DIF.setCaption(actionLabelHandle1, "Start Rotation");
			actionRotation = 0;
		  } else {
            lighthouse3DIF.setCaption(actionLabelHandle1, "Stop Rotation");
			actionRotation = 1;
		  }

          // Save old mouse states
	      lastLeftMousePressed = leftMousePressed;
	      lastMiddleMousePressed = middleMousePressed;
	      lastRightMousePressed = rightMousePressed;

		  // Immediatly leave with Ok!
		  return 1;
		}

		// Check if we clicked to the "create pyramid" button
		if (lighthouse3DIF.isOverGUIElement(objectButtonHandle1, horzPos, vertPos)) {
  	      lighthouse3DIF.setVisible(sizeButtonHandle1, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle2, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle3, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle4, true);

		  currentMenuDepth = 1;
		  currentObjectChoosen = 1;
		}

		// Check if we clicked to the "create cube" button
		if (lighthouse3DIF.isOverGUIElement(objectButtonHandle2, horzPos, vertPos)) {
  	      lighthouse3DIF.setVisible(sizeButtonHandle1, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle2, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle3, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle4, true);

		  currentMenuDepth = 1;
		  currentObjectChoosen = 2;
		}

		// Check if we clicked to the "create cone" button
		if (lighthouse3DIF.isOverGUIElement(objectButtonHandle3, horzPos, vertPos)) {
  	      lighthouse3DIF.setVisible(sizeButtonHandle1, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle2, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle3, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle4, true);

		  currentMenuDepth = 1;
		  currentObjectChoosen = 3;
		}
        
		// Check if we clicked to the "create cone" button
		if (lighthouse3DIF.isOverGUIElement(objectButtonHandle4, horzPos, vertPos)) {
  	      lighthouse3DIF.setVisible(sizeButtonHandle1, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle2, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle3, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle4, true);

		  currentMenuDepth = 1;
		  currentObjectChoosen = 4;
		}
        
		// Check if we clicked to the "create sphere" button
		if (lighthouse3DIF.isOverGUIElement(objectButtonHandle5, horzPos, vertPos)) {
  	      lighthouse3DIF.setVisible(sizeButtonHandle1, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle2, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle3, true);
  	      lighthouse3DIF.setVisible(sizeButtonHandle4, true);

		  currentMenuDepth = 1;
		  currentObjectChoosen = 5;
		}

		// Choose size of new object
		if (currentMenuDepth == 1) {
		  // Small-Button
  		  if (lighthouse3DIF.isOverGUIElement(sizeButtonHandle1, horzPos, vertPos)) {
  	        lighthouse3DIF.setVisible(positionButtonHandle1, true);
  	        lighthouse3DIF.setVisible(positionButtonHandle2, true);
  	        lighthouse3DIF.setVisible(posWindowHandle, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle1, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle2, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle3, true);		

		    currentObjectSize = 1;
			currentMenuDepth = 2;

            currentObjectX = 0;
			currentObjectY = 0;
			currentObjectZ = 0;

			sprintf(tmpString, "x-Coordinate: %i", currentObjectX);
	        lighthouse3DIF.setCaption(posLabelHandle1, tmpString);
  		    sprintf(tmpString, "y-Coordinate: %i", currentObjectY);
 	        lighthouse3DIF.setCaption(posLabelHandle2, tmpString);
		    sprintf(tmpString, "z-Coordinate: %i", currentObjectZ);
	        lighthouse3DIF.setCaption(posLabelHandle3, tmpString);
		  }
		  // Medium-Button
  		  if (lighthouse3DIF.isOverGUIElement(sizeButtonHandle2, horzPos, vertPos)) {
  	        lighthouse3DIF.setVisible(positionButtonHandle1, true);
  	        lighthouse3DIF.setVisible(positionButtonHandle2, true);
  	        lighthouse3DIF.setVisible(posWindowHandle, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle1, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle2, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle3, true);		

			currentObjectSize = 2;
			currentMenuDepth = 2;
		  
            currentObjectX = 0;
			currentObjectY = 0;
			currentObjectZ = 0;

			sprintf(tmpString, "x-Coordinate: %i", currentObjectX);
	        lighthouse3DIF.setCaption(posLabelHandle1, tmpString);
  		    sprintf(tmpString, "y-Coordinate: %i", currentObjectY);
 	        lighthouse3DIF.setCaption(posLabelHandle2, tmpString);
		    sprintf(tmpString, "z-Coordinate: %i", currentObjectZ);
	        lighthouse3DIF.setCaption(posLabelHandle3, tmpString);
		  }
		  // Large-Button
  		  if (lighthouse3DIF.isOverGUIElement(sizeButtonHandle3, horzPos, vertPos)) {
  	        lighthouse3DIF.setVisible(positionButtonHandle1, true);
  	        lighthouse3DIF.setVisible(positionButtonHandle2, true);
  	        lighthouse3DIF.setVisible(posWindowHandle, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle1, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle2, true);		
  	        lighthouse3DIF.setVisible(posLabelHandle3, true);		

			currentObjectSize = 3;
			currentMenuDepth = 2;

            currentObjectX = 0;
			currentObjectY = 0;
			currentObjectZ = 0;

			sprintf(tmpString, "x-Coordinate: %i", currentObjectX);
	        lighthouse3DIF.setCaption(posLabelHandle1, tmpString);
  		    sprintf(tmpString, "y-Coordinate: %i", currentObjectY);
 	        lighthouse3DIF.setCaption(posLabelHandle2, tmpString);
		    sprintf(tmpString, "z-Coordinate: %i", currentObjectZ);
	        lighthouse3DIF.setCaption(posLabelHandle3, tmpString);
		  }
		  // NoObj-Button
  		  if (lighthouse3DIF.isOverGUIElement(sizeButtonHandle4, horzPos, vertPos)) {
    	    lighthouse3DIF.setVisible(sizeButtonHandle1, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle2, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle3, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle4, false);

  	        lighthouse3DIF.setVisible(positionButtonHandle1, false);
  	        lighthouse3DIF.setVisible(positionButtonHandle2, false);
  	        lighthouse3DIF.setVisible(posWindowHandle, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle1, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle2, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle3, false);		

			currentObjectSize = 0;
			currentMenuDepth = 0;
		  }
		}

		// Choose position of object
		if (currentMenuDepth == 2) {
		  // Create Object Button
  		  if (lighthouse3DIF.isOverGUIElement(positionButtonHandle1, horzPos, vertPos)) {
		    // Create pyramid
  	        if (currentObjectChoosen == 1) {
			  // Choose object layout
              if (currentObjectSize == 1)
                lighthouse3DIF.setPyramidParams(30);
              if (currentObjectSize == 2)
				lighthouse3DIF.setPyramidParams(60);
              if (currentObjectSize == 3)
				lighthouse3DIF.setPyramidParams(90);

			  if (!lighthouse3DIF.createPyramid("../resources/texture_pyr.bmp"))
		        exit(0);

			  // Necessary to finalize object later on
			  lastAddedObject = lighthouse3DIF.getLastObjectReference();

			  // We have finished
			  currentObjectChoosen = 0;
			}
		    // Create cube
  	        if (currentObjectChoosen == 2) {
			  // Choose object layout
              if (currentObjectSize == 1)
                lighthouse3DIF.setCubeParams(30, false, false);

              if (currentObjectSize == 2)
                lighthouse3DIF.setCubeParams(60, false, false);

              if (currentObjectSize == 3)
                lighthouse3DIF.setCubeParams(90, false, false);

			  if (!lighthouse3DIF.createCube("../resources/texture_cube.bmp"))
		        exit(0);

			  // Necessary to finalize object later on
			  lastAddedObject = lighthouse3DIF.getLastObjectReference();

			  // We have finished
			  currentObjectChoosen = 0;
			}
		    // Create cylinder
  	        if (currentObjectChoosen == 3) {
			  // Choose object layout
              if (currentObjectSize == 1)
                lighthouse3DIF.setCylinderParams(30, 25, 25, 40);

              if (currentObjectSize == 2)
                lighthouse3DIF.setCylinderParams(60, 50, 50, 40);

              if (currentObjectSize == 3)
                lighthouse3DIF.setCylinderParams(90, 75, 75, 40);

	          if (!lighthouse3DIF.createCylinder("../resources/texture_cyl.bmp"))
		        exit(0);

			  // Necessary to finalize object later on
			  lastAddedObject = lighthouse3DIF.getLastObjectReference();

			  // We have finished
			  currentObjectChoosen = 0;
			}
		    // Create cone
  	        if (currentObjectChoosen == 4) {
			  // Choose object layout
              if (currentObjectSize == 1)
                lighthouse3DIF.setConeParams(30, 25, 40);

              if (currentObjectSize == 2)
                lighthouse3DIF.setConeParams(60, 50, 40);

              if (currentObjectSize == 3)
                lighthouse3DIF.setConeParams(90, 75, 40);

	          if (!lighthouse3DIF.createCone("../resources/texture_cone.bmp"))
		        exit(0);

			  // Necessary to finalize object later on
			  lastAddedObject = lighthouse3DIF.getLastObjectReference();

			  // We have finished
			  currentObjectChoosen = 0;
			}
		    // Create sphere
  	        if (currentObjectChoosen == 5) {
			  // Choose object layout
              if (currentObjectSize == 1)
                lighthouse3DIF.setSphereParams(20, 80, 30);

              if (currentObjectSize == 2)
                lighthouse3DIF.setSphereParams(20, 80, 60);

              if (currentObjectSize == 3)
                lighthouse3DIF.setSphereParams(20, 80, 90);

			  if (!lighthouse3DIF.createSphere("../resources/texture_sphere.tga"))
		        exit(0);

			  // Necessary to finalize object later on
			  lastAddedObject = lighthouse3DIF.getLastObjectReference();

			  // We have finished
			  currentObjectChoosen = 0;
			}

    	    lighthouse3DIF.setVisible(sizeButtonHandle1, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle2, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle3, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle4, false);

  	        lighthouse3DIF.setVisible(positionButtonHandle1, false);
  	        lighthouse3DIF.setVisible(positionButtonHandle2, false);
  	        lighthouse3DIF.setVisible(posWindowHandle, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle1, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle2, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle3, false);		

			currentObjectSize = 0;
			currentMenuDepth = 0;
		  }
		  // NoObj-Button
  		  if (lighthouse3DIF.isOverGUIElement(positionButtonHandle2, horzPos, vertPos)) {
    	    lighthouse3DIF.setVisible(sizeButtonHandle1, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle2, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle3, false);
  	        lighthouse3DIF.setVisible(sizeButtonHandle4, false);

  	        lighthouse3DIF.setVisible(positionButtonHandle1, false);
  	        lighthouse3DIF.setVisible(positionButtonHandle2, false);
  	        lighthouse3DIF.setVisible(posWindowHandle, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle1, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle2, false);		
  	        lighthouse3DIF.setVisible(posLabelHandle3, false);		

			currentObjectSize = 0;
			currentMenuDepth = 0;
		  }
		}
    	// Keep in mind we need to request a screen update
		requestScreenUpdate = 1;
	}

	// Second move along
    
	// If we are not currently working in the menu
	if (currentMenuDepth == 0) {
	// left mouse handler: move camera along current camera view vector
	if (leftMousePressed == 1) {
		// Move ahead camera
		lighthouse3DIF.moveAheadCamera(3);

    	// Keep in mind we need to request a screen update
		requestScreenUpdate = 1;
	}

	// middle mouse handler: translate camera view vector
	if (middleMousePressed == 1) {
		// First time we only save the coordinates
		if (lastMouseX != 0) {
		  if (curMouseX < lastMouseX)
			tmpX = abs(curMouseX-lastMouseX)/3;
		  if (curMouseX > lastMouseX)
			tmpX = -abs(curMouseX-lastMouseX)/3;
		  if (curMouseY > lastMouseY)
  			tmpY = abs(curMouseY-lastMouseY)/3;
	  	  if (curMouseY < lastMouseY)
			tmpY = -abs(curMouseY-lastMouseY)/3;

		  if (tmpX != 0)
  		    lighthouse3DIF.moveLeftCamera((float) tmpX);
		  if (tmpY != 0)
		    lighthouse3DIF.moveDownCamera((float) tmpY);
		}

    	// Keep in mind we need to request a screen update
		requestScreenUpdate = 1;
	}

	// right mouse handler: rotate camera view vector
	if (rightMousePressed == 1) {
		// First time we only save the coordinates
		if (lastMouseX != 0) {
		  if (curMouseX < lastMouseX)
			tmpX = abs(curMouseX-lastMouseX)/3;
		  if (curMouseX > lastMouseX)
			tmpX = -abs(curMouseX-lastMouseX)/3;
		  if (curMouseY > lastMouseY)
  			tmpY = abs(curMouseY-lastMouseY)/3;
	  	  if (curMouseY < lastMouseY)
			tmpY = -abs(curMouseY-lastMouseY)/3;

		  if (tmpX != 0)
  		    lighthouse3DIF.turnLeftCamera(tmpX);
		  if (tmpY != 0)
  		    lighthouse3DIF.turnDownCamera(tmpY);
		}

    	// Keep in mind we need to request a screen update
		requestScreenUpdate = 1;
	}

	}

	// Save old coordinates
	lastMouseX = curMouseX;
	lastMouseY = curMouseY;

    // Save old mouse states
	lastLeftMousePressed = leftMousePressed;
	lastMiddleMousePressed = middleMousePressed;
	lastRightMousePressed = rightMousePressed;

	// Ok
	return 1;
}
